package com.cskaoyan.user.service.impl;

import com.cskaoyan.mall.commons.constant.SysRetCodeConstants;
import com.cskaoyan.mall.commons.exception.ValidateException;
import com.cskaoyan.mall.commons.util.ObjectEmptyUtils;
import com.cskaoyan.user.converter.UserConverterMapper;
import com.cskaoyan.user.dal.entitys.Member;
import com.cskaoyan.user.dal.entitys.UserVerify;
import com.cskaoyan.user.dal.persistence.MemberMapper;
import com.cskaoyan.user.dal.persistence.UserVerifyMapper;
import com.cskaoyan.user.form.UserRegisterRequest;
import com.cskaoyan.user.form.UserVerifyRequest;
import com.cskaoyan.user.service.IUserRegisterService;
import com.cskaoyan.user.utils.AffectValid;
import com.sun.javafx.binding.StringFormatter;
import javafx.beans.binding.StringExpression;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Auth: 杨宇健
 * Time: 2023/1/9 21:46
 * Description: 用户注册实现类
 **/

@Service
public class UserRegisterServiceImpl implements IUserRegisterService {

    @Autowired
    MemberMapper memberMapper;

    @Autowired
    UserVerifyMapper userVerifyMapper;

    @Autowired
    UserConverterMapper userConverterMapper;

    //邮件发送组件
    @Autowired
    JavaMailSender mailSender;

    @Value("${email.text}")
    String emailText;

    @Value("${spring.mail.username}")
    String mailUser;

    /**
     * 注册方法
     * 1. 查询member中是否已存在member，根据用户名查询, 如果用户名已存在就抛异常， 因为verify表跟 member表没有一一对应的关系
     * 2. 密码加密处理
     * @param request
     * @return void
     * @author 杨宇健
     * @since 2023/01/09 21:51
     */
    @Transactional
    @Override
    public void register(UserRegisterRequest request) {
        if (ObjectEmptyUtils.isContainsNull(request)) {
            throw new ValidateException(SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getCode(), SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getMessage());
        }

        Member member = new Member();
        //BeanUtils.copyProperties(request, member);
        member.setUsername(request.getUserName());
        //md5加密
        String md5pwd = DigestUtils.md5DigestAsHex(request.getUserPwd().getBytes());
        member.setPassword(md5pwd);
        member.setEmail(request.getEmail());
        //查询是否存在重复数据，包括 name 或 email
        List<Member> members = selectMemberByNameOrEmail(request, member);
        if (members.size() > 0) {
            // 数据重复，抛出异常
            throw new ValidateException(SysRetCodeConstants.DATA_REPEATED.getCode(), SysRetCodeConstants.DATA_REPEATED.getMessage());
        }

        //TODO 设置密码为md5
        Date date = new Date();
        member.setCreated(date);
        member.setUpdated(date);

        //member表插入数据
        int affect1 = memberMapper.insertSelective(member);
        //校验，插入失败则抛数据库异常
        AffectValid.affectValid(affect1);


        UserVerify userVerify = new UserVerify();
        userVerify.setUsername(member.getUsername());
        userVerify.setRegisterDate(date);
        UUID uuid = UUID.randomUUID();
        userVerify.setUuid(uuid.toString());
        userVerify.setIsExpire("N");
        userVerify.setIsVerify("N");

        //插入数据验证表格
        int affect2 = userVerifyMapper.insertSelective(userVerify);
        //校验，插入失败则抛数据库异常
        AffectValid.affectValid(affect2);

        System.out.println("插入成功！");

        try {
            mailTest(userVerify.getUsername(), uuid.toString(), member.getEmail());
        }catch (Exception e){
            // TODO 杨宇健 发邮件异常
            throw new ValidateException(SysRetCodeConstants.SYSTEM_ERROR.getCode(), SysRetCodeConstants.SYSTEM_ERROR.getMessage());
        }

    }

    private List<Member> selectMemberByNameOrEmail(UserRegisterRequest request, Member member) {

        Example example = new Example(Member.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", member.getUsername());
        criteria.orEqualTo("email", member.getEmail());

        List<Member> members = memberMapper.selectByExample(example);
        return members;
    }

    @Async("asyncExecutor")
    public void mailTest(String username ,String uuid, String toEmail){
        System.out.println(mailUser);
        SimpleMailMessage message = new SimpleMailMessage();

        message.setFrom(mailUser);
        message.setSubject("测试用例：csmall激活");

        StringExpression text = StringFormatter.format(emailText, username, uuid);
        message.setText(text.getValue());
        message.setTo(toEmail);
        mailSender.send(message);
        System.out.println("邮件发送成功");
    }

    @Transactional
    @Override
    public void verify(UserVerifyRequest request) {

        if (ObjectEmptyUtils.isContainsNull(request)) {
            //参数不能为空
            throw new ValidateException(SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getCode(), SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getMessage());
        }

        Example exampleVerify = new Example(UserVerify.class);
        Example.Criteria criteriaVerify = exampleVerify.createCriteria();
        criteriaVerify.andEqualTo("username", request.getUsername());
        criteriaVerify.andEqualTo("uuid", request.getUuid());
        List<UserVerify> userVerifies = userVerifyMapper.selectByExample(exampleVerify);
        if (userVerifies.size() == 0) {
            //用户不存在
            throw new ValidateException(SysRetCodeConstants.DATA_NOT_EXIST.getCode(), SysRetCodeConstants.DATA_NOT_EXIST.getMessage());
        }
        for (UserVerify verify : userVerifies) {
            //已过期的数据抛出异常（理论上uuid只会生成唯一数据，所以list size == 1）
            if ("Y".equals(verify.getIsExpire()) ) {
                throw new ValidateException(SysRetCodeConstants.DATA_EXPIRE.getCode(), SysRetCodeConstants.DATA_EXPIRE.getMessage());
            }
            //已验证过的数据
            if ("Y".equals(verify.getIsVerify())){
                throw new ValidateException(SysRetCodeConstants.DATA_USED.getCode(), SysRetCodeConstants.DATA_USED.getMessage());
            }
        }
        UserVerify verify = userVerifies.get(0);
        verify.setIsVerify("Y");
        //verify表修改为已验证
        userVerifyMapper.updateByPrimaryKey(verify);



        Example memberExample = new Example(Member.class);
        Example.Criteria criteria = memberExample.createCriteria();
        criteria.andEqualTo("username", request.getUsername());

        List<Member> memberList = memberMapper.selectByExample(memberExample);
        if (memberList == null || memberList.size() == 0) {
            //数据库异常，缺少应该被验证的数据
            throw new ValidateException(SysRetCodeConstants.DB_EXCEPTION.getCode(), SysRetCodeConstants.DB_EXCEPTION.getMessage());
        }

        for (Member member : memberList) {
            if ("Y".equals(member.getIsVerified())) {
                //账号已存在
                throw new ValidateException(SysRetCodeConstants.DATA_REPEATED.getCode(), SysRetCodeConstants.DATA_REPEATED.getMessage());
            }
        }
        Member member = memberList.get(memberList.size() - 1);
        member.setIsVerified("Y");
        member.setUpdated(new Date());
        //用户信息改成已验证
        memberMapper.updateByPrimaryKeySelective(member);

    }
}
